package com.zxy.ziems.server.device.service.impl;

import cn.hutool.core.util.StrUtil;
import com.zxy.ziems.server.device.convertor.DeviceConvertor;
import com.zxy.ziems.server.device.mapper.DeviceTypePropertyMapper;
import com.zxy.ziems.server.device.pojo.dto.DeviceTypePropertyDTO;
import com.zxy.ziems.server.device.pojo.entity.DataTypeEntity;
import com.zxy.ziems.server.device.pojo.entity.DataUnitEntity;
import com.zxy.ziems.server.device.pojo.entity.DevicePropertyEntity;
import com.zxy.ziems.server.device.pojo.entity.DeviceTypePropertyEntity;
import com.zxy.ziems.server.device.pojo.vo.DataTypeVO;
import com.zxy.ziems.server.device.pojo.vo.DevicePropertyVO;
import com.zxy.ziems.server.device.service.DataTypeService;
import com.zxy.ziems.server.device.service.DataUnitService;
import com.zxy.ziems.server.device.service.DevicePropertyService;
import com.zxy.ziems.server.device.service.DeviceTypePropertyService;
import com.zxy.ziems.server.mybatis.core.query.WrapperX;
import com.zxy.ziems.server.mybatis.core.service.ServiceImplX;
import com.zxy.ziems.server.service.DictItemService;
import com.zxy.ziems.server.utils.AssertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 设备类型 关联属性
 * @author 10348359
 * @create 2024-03-20 22:43
 */
@Service
public class DeviceTypePropertyServiceImpl extends ServiceImplX<DeviceTypePropertyMapper, DeviceTypePropertyEntity> implements DeviceTypePropertyService {
    @Override
    public void add(DeviceTypePropertyDTO dto) {
        AssertUtil.isNull(getByName(dto.getName(), dto.getDeviceTypeCode()), "设备属性名称重复");
        AssertUtil.nonNull(dataTypeService.getById(dto.getDataTypeId()), "设备属性不存在");
        AssertUtil.nonNull(dataUnitService.getById(dto.getUnitId()), "设备的数据单位不存在");
        DeviceTypePropertyEntity entity = DeviceConvertor.INSTANCE.deviceTypePropertyDTOConvert2DO(dto);
        save(entity);
    }

    @Override
    public void update(DeviceTypePropertyDTO dto) {
        AssertUtil.nonNull(getById(dto.getId()), "设备属性不存在");
        DeviceTypePropertyEntity old = getByName(dto.getName(), dto.getDeviceTypeCode());
        AssertUtil.isTrue(Objects.isNull(old) || old.getId().equals(dto.getId()), "设备属性重复");
        AssertUtil.nonNull(dataTypeService.getById(dto.getDataTypeId()), "设备属性不存在");
        AssertUtil.nonNull(dataUnitService.getById(dto.getUnitId()), "设备的数据单位不存在");
        DeviceTypePropertyEntity entity = DeviceConvertor.INSTANCE.deviceTypePropertyDTOConvert2DO(dto);
        updateById(entity);
    }

    @Override
    public void deleteById(String id) {
        if (StrUtil.isBlank(id)) {
            return;
        }
        removeById(id);
    }

    @Override
    public DeviceTypePropertyEntity getByDevice(String deviceType, String dataTypeId) {
        return getOne(WrapperX.<DeviceTypePropertyEntity>lambdaQuery()
                .eq(DeviceTypePropertyEntity::getDeviceTypeCode, deviceType)
                .eq(DeviceTypePropertyEntity::getDataTypeId, dataTypeId)
        );
    }

    @Override
    public List<DeviceTypePropertyEntity> listByDeviceType(String deviceType) {
        return list(DeviceTypePropertyEntity::getDeviceTypeCode, deviceType);
    }

    @Override
    public List<DevicePropertyVO> viewListByDeviceType(String deviceType) {
        List<DeviceTypePropertyEntity> list = list(DeviceTypePropertyEntity::getDeviceTypeCode, deviceType);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>(0);
        }
        List<String> propertyIdList = list.stream().map(DeviceTypePropertyEntity::getDataTypeId).toList();
        List<String> unitIdList = list.stream().map(DeviceTypePropertyEntity::getUnitId).toList();
        List<DataUnitEntity> unitList = dataUnitService.listByIdList(unitIdList);
        List<DataTypeEntity> dataTypeEntities = dataTypeService.listByIdList(propertyIdList);
        Map<String, DataUnitEntity> unitMap = unitList.stream().collect(Collectors.toMap(DataUnitEntity::getId, (a) -> a));
        Map<String, DataTypeEntity> dataTypeEntityMap = dataTypeEntities.stream().collect(Collectors.toMap(DataTypeEntity::getId, (a) -> a));

        DeviceConvertor instance = DeviceConvertor.INSTANCE;
        List<DevicePropertyVO> result = list.stream()
                .map((entity) -> instance.deviceTypePropertyDOConvert2VO(
                        entity,
                        dataTypeEntityMap.get(entity.getDataTypeId()),
                        unitMap.get(entity.getUnitId()),
                        DevicePropertyVO.META_STATUS
                        ))
                .toList();
        return result;
    }

    @Override
    public List<DataTypeVO> viewDataTypeListByDeviceType(String deviceType) {
        List<DeviceTypePropertyEntity> list = list(DeviceTypePropertyEntity::getDeviceTypeCode, deviceType);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>(0);
        }
        List<String> propertyIdList = list.stream().map(DeviceTypePropertyEntity::getDataTypeId).toList();
        List<DataTypeEntity> dataTypeEntities = dataTypeService.listByIdList(propertyIdList);
        Map<String, DataTypeEntity> dataTypeEntityMap = dataTypeEntities.stream().collect(Collectors.toMap(DataTypeEntity::getId, (a) -> a));

        List<DataTypeVO> result = list.stream()
                .map((entity) -> {
                    DataTypeEntity dataTypeEntity = dataTypeEntityMap.get(entity.getDataTypeId());
                        DataTypeVO vo = new DataTypeVO();
                        vo.setId(dataTypeEntity.getId());
                        vo.setCode(dataTypeEntity.getCode());
                        vo.setName(entity.getName());
                        return vo;
                    }
                )
                .toList();
        return result;
    }

    @Override
    public List<DataTypeVO> viewDataTypeListByDeviceId(String deviceId) {
        List<DevicePropertyEntity> list = devicePropertyService.listByDeviceId(deviceId);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>(0);
        }
        List<String> propertyIdList = list.stream().map(DevicePropertyEntity::getDataTypeId).toList();
        List<DataTypeEntity> dataTypeEntities = dataTypeService.listByIdList(propertyIdList);
        Map<String, DataTypeEntity> dataTypeEntityMap = dataTypeEntities.stream().collect(Collectors.toMap(DataTypeEntity::getId, (a) -> a));

        List<DataTypeVO> result = list.stream()
                .map((entity) -> {
                            DataTypeEntity dataTypeEntity = dataTypeEntityMap.get(entity.getDataTypeId());
                            DataTypeVO vo = new DataTypeVO();
                            vo.setId(dataTypeEntity.getId());
                            vo.setCode(dataTypeEntity.getCode());
                            vo.setName(entity.getName());
                            vo.setDictItemList(dictItemService.getByDictCode(entity.getDictCode()));
                            return vo;
                        }
                )
                .toList();
        return result;
    }

    private DeviceTypePropertyEntity getByName(String name, String deviceTypeCode) {
        return getOne(WrapperX.<DeviceTypePropertyEntity>lambdaQuery()
                .eq(DeviceTypePropertyEntity::getName, name)
                .eq(DeviceTypePropertyEntity::getDeviceTypeCode, deviceTypeCode)
        );
    }

    private DataTypeService dataTypeService;

    @Autowired
    public void setDataTypeService(DataTypeService dataTypeService) {
        this.dataTypeService = dataTypeService;
    }

    private DataUnitService dataUnitService;



    @Autowired
    public void setDataUnitService(DataUnitService dataUnitService) {
        this.dataUnitService = dataUnitService;
    }

    private DevicePropertyService devicePropertyService;

    @Lazy
    @Autowired
    public void setDevicePropertyService(DevicePropertyService devicePropertyService){
        this.devicePropertyService = devicePropertyService;
    }

    private DictItemService dictItemService;


    @Autowired
    public void setDictItemService(DictItemService dictItemService) {
        this.dictItemService = dictItemService;
    }
}
